/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop.framework;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.aopalliance.intercept.Interceptor;
import org.aopalliance.intercept.MethodInterceptor;

import org.springframework.aop.Advisor;
import org.springframework.aop.IntroductionAdvisor;
import org.springframework.aop.IntroductionAwareMethodMatcher;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry;
import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry;
import org.springframework.lang.Nullable;

/**
 * A simple but definitive way of working out an advice chain for a Method,
 * given an {@link Advised} object. Always rebuilds each advice chain;
 * caching can be provided by subclasses.
 *
 * @author Juergen Hoeller
 * @author Rod Johnson
 * @author Adrian Colyer
 * @since 2.0.3
 */
@SuppressWarnings("serial")
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

	/**
	 * 获取拦截器和动态拦截建议列表。
	 * 此方法负责处理Spring AOP中的拦截器和引入（introduction）的逻辑，根据给定的方法和目标类，
	 * 从配置中解析出相应的拦截器链。
	 *
	 * @param config 提供advisors和其它配置信息的对象。
	 * @param method 被代理的方法。
	 * @param targetClass 目标类的Class对象，如果为null，则使用方法的声明类。
	 * @return 拦截器和动态拦截建议的列表，列表中的元素可能是MethodInterceptor实例，
	 *         也可能是InterceptorAndDynamicMethodMatcher实例。
	 */
	@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
	        Advised config, Method method, @Nullable Class<?> targetClass) {

	    // 处理引入（introduction）逻辑，同时需保持最终列表中的顺序。
	    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
	    Advisor[] advisors = config.getAdvisors();
	    List<Object> interceptorList = new ArrayList<>(advisors.length);
	    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	    Boolean hasIntroductions = null;

	    // 遍历所有的advisor，解析出对应的拦截器
	    for (Advisor advisor : advisors) {
	        if (advisor instanceof PointcutAdvisor) {
	            // 条件性地添加pointcut advisor
	            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
	            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
	                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
	                boolean match;
	                if (mm instanceof IntroductionAwareMethodMatcher) {
	                    // 处理引入感知的方法匹配器
	                    if (hasIntroductions == null) {
	                        hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
	                    }
	                    match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
	                }
	                else {
	                    // 标准方法匹配逻辑
	                    match = mm.matches(method, actualClass);
	                }
	                if (match) {
	                    // 根据是否是运行时匹配，添加不同的拦截器包装
	                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
	                    if (mm.isRuntime()) {
	                        for (MethodInterceptor interceptor : interceptors) {
	                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
	                        }
	                    }
	                    else {
	                        interceptorList.addAll(Arrays.asList(interceptors));
	                    }
	                }
	            }
	        }
	        else if (advisor instanceof IntroductionAdvisor) {
	            // 处理引入advisor
	            IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
	            if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
	                Interceptor[] interceptors = registry.getInterceptors(advisor);
	                interceptorList.addAll(Arrays.asList(interceptors));
	            }
	        }
	        else {
	            // 处理非pointcut类型的advisor
	            Interceptor[] interceptors = registry.getInterceptors(advisor);
	            interceptorList.addAll(Arrays.asList(interceptors));
	        }
	    }

	    return interceptorList;
	}

	/**
	 * Determine whether the Advisors contain matching introductions.
	 */
	private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
		for (Advisor advisor : advisors) {
			if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (ia.getClassFilter().matches(actualClass)) {
					return true;
				}
			}
		}
		return false;
	}

}
